﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using OfficeOpenXml;
using OfficeOpenXml.DataValidation;

namespace ShieldTunnel2.PrepareData
{
	class Program
	{
		const string FileFolderPath = @"..\..\..\ShieldTunnel2\bin\Debug\Output";
		const string ExpertFormFilePrefix = "专家调查表_";

		static void Main(string[] args)
		{
			Console.WriteLine("Preparing data for ShieldTunnel project ......\n");

			//CreateRiskEventListFile();
			FillExpertRiskEvalForms();

			//
			Console.WriteLine("\nDone!");
			Console.ReadKey();
		}

		public static void CreateRiskEventListFile()
		{
			Console.WriteLine("Creating risk factor list file ......");

			var rootRiskEvent = new PotentialRiskEvent()
			{
				Name = "地铁盾构法隧道工程安全风险",
				Level = 1,
				ChildRiskEvents = new List<PotentialRiskEvent>()
				{
					new PotentialRiskEvent()
					{
						Name = "工作井施工风险", Level = 2,
						ChildRiskEvents = new List<PotentialRiskEvent>()
						{
							new PotentialRiskEvent()
							{
								Name = "涌水涌砂", Level = 3,
								ChildRiskEvents = new List<PotentialRiskEvent>()
								{
									new PotentialRiskEvent()
									{
										Name = "地连墙施工不到位", Level = 4,
									},
									new PotentialRiskEvent()
									{
										Name = "井内承压水处理不当", Level = 4,
									},
								}
							},
							new PotentialRiskEvent()
							{
								Name = "坑底隆起", Level = 3,
								ChildRiskEvents = new List<PotentialRiskEvent>()
								{
									new PotentialRiskEvent()
									{
										Name = "围护结构插入坑底深度不足", Level = 4,
									},
									new PotentialRiskEvent()
									{
										Name = "地基加固失效", Level = 4,
									},
									new PotentialRiskEvent()
									{
										Name = "井内承压水处理不当", Level = 4,
									},
								}
							},
							new PotentialRiskEvent()
							{
								Name = "基坑失稳", Level = 3,
							},
						}
					},
					new PotentialRiskEvent()
					{
						Name = "盾构始发前准备工作风险", Level = 2,
					},
					new PotentialRiskEvent()
					{
						Name = "盾构始发风险", Level = 2,
						ChildRiskEvents = new List<PotentialRiskEvent>()
						{
							new PotentialRiskEvent()
							{
								Name = "土体涌入工作井", Level = 3,
							},
							new PotentialRiskEvent()
							{
								Name = "盾构“抬头”", Level = 3,
							},
						}
					},
				}
			};
			var filePath = "PotentialRiskEvent_10261718.json";
			var text = File.ReadAllText(filePath);
			rootRiskEvent = JsonConvert.DeserializeObject<PotentialRiskEvent>(text);

			var fileName = "PotentialRiskEvent.json";
			filePath = Path.Combine(FileFolderPath, fileName);
			text = JsonConvert.SerializeObject(rootRiskEvent, Formatting.Indented);
			File.WriteAllText(filePath, text);
		}

		public static void FillExpertRiskEvalForms()
		{
			Debug.Assert(Directory.Exists(FileFolderPath));
			Console.WriteLine("Filling expert risk eval forms ......");

			void FillValidationRangeWithRandomValue(ExcelWorksheet sheet)
			{
				Debug.Assert(sheet?.DataValidations != null);

				var random = new Random();
				foreach (var validation in sheet.DataValidations)
				{
					var list = validation as ExcelDataValidationList;
					Debug.Assert(list != null);
					var options = list.Formula.Values;
					Debug.Assert(options != null && options.Count > 0);

					var startRow = list.Address.Start.Row;
					var startCol = list.Address.Start.Column;
					var endRow = list.Address.End.Row;
					var endCol = list.Address.End.Column;
					Debug.Assert(startRow <= endRow && startCol <= endCol);
					for (var i = startRow; i <= endRow; i++)
					{
						for (var j = startCol; j <= endCol; j++)
						{
							//var index = random.Next(0, options.Count - 1);
							var index = random.Next(2, options.Count - 1);
							sheet.Cells[i, j].Value = options[index];
						}
					}
				}
			}

			var fileNames = Directory.GetFiles(FileFolderPath)
				.Select(Path.GetFileNameWithoutExtension)
				.Where(fn => fn.StartsWith(ExpertFormFilePrefix))
				.ToList();
			var expertNames = fileNames
				.Select(fn => fn.Substring(ExpertFormFilePrefix.Length))
				.ToList();
			foreach (var expertName in expertNames)
			{
				var destFilePath = Path.Combine(FileFolderPath, 
					$"{ExpertFormFilePrefix}{expertName}.xlsx");
				Debug.Assert(File.Exists(destFilePath));

				var fi = new FileInfo(destFilePath);
				using (var excelPackage = new ExcelPackage(fi))
				{
					var workbook = excelPackage.Workbook;
					var sheets = workbook.Worksheets;

					//
					// 专家个人信息
					//
					var sheetName = "专家个人信息";
					Debug.Assert(sheets.Any(s => s.Name == sheetName));
					FillValidationRangeWithRandomValue(sheets[sheetName]);

					//
					// 风险事件重要度
					//
					sheetName = "风险事件重要度";
					Debug.Assert(sheets.Any(s => s.Name == sheetName));
					FillValidationRangeWithRandomValue(sheets[sheetName]);

					//
					// 风险事件发生概率
					//
					sheetName = "风险事件发生概率";
					Debug.Assert(sheets.Any(s => s.Name == sheetName));
					FillValidationRangeWithRandomValue(sheets[sheetName]);

					//
					// 风险事件损失
					//
					sheetName = "风险事件损失";
					Debug.Assert(sheets.Any(s => s.Name == sheetName));
					FillValidationRangeWithRandomValue(sheets[sheetName]);

					//
					// 总损失重要度
					//
					sheetName = "总损失重要度";
					Debug.Assert(sheets.Any(s => s.Name == sheetName));
					FillValidationRangeWithRandomValue(sheets[sheetName]);

					//
					excelPackage.Save();
				}
			}
		}
	}

	public class PotentialRiskEvent
	{
		public string Name { get; set; }
		public int Level { get; set; }

		[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
		public IList<PotentialRiskEvent> ChildRiskEvents { get; set; }
	}
}
